/**
 *  Item.java : IceBird project
 *  14:49:30 
 */
package icebird.compiler.x86.old;

import icebird.metadata.BasicType;

/**
 * @author Sergey Shulepoff[Knott]
 */
public abstract class Item {

	public static final byte CONSTANT = 0x01;
	public static final byte GPR = 0x02;
	public static final byte XMM = 0x04;
	public static final byte FPUSTACK = 0x08;
	public static final byte STACK = 0x10;
	public static final byte LOCAL = 0x20;
	
	private byte kind;
	private short bpOffset;
	
	protected X86Register.XMM xmm;
	
	protected final ItemFactory creator;
	
	/**
	 * Create this instance.
	 * @param owner
	 */
	protected Item(ItemFactory owner) {
		creator = owner;
	}
	
	/**
	 * Initialize this item.
	 * @return void
	 */
	protected final void init(byte k, short bp, X86Register.XMM xmm) {
		kind = k;
		bpOffset = bp;
		
		this.xmm = xmm;
	}
	
	/**
	 * Raise not implemented error.
	 */
	public static void notImplemented() {
		throw new Error("Not implemented.");
	}
	
	/**
	 * Gets type of this item.
	 * @return BasicType
	 */
	public abstract BasicType getType();
	
	/**
	 * Gets kind of this item.
	 * @return byte
	 */
	public final byte getKind() {
		return kind;
	}
	
	/**
	 * Set new kind.
	 * @return void
	 */
	public final void setKind(byte v) {
		kind = v;
	}
	
	/** Is this item on the stack */
	final boolean isStack() {
		return (kind == STACK);
	}

	/** Is this item in a general purpose register */
	final boolean isGPR() {
		return (kind == GPR);
	}

	/** Is this item in a SSE register */
	final boolean isXMM() {
		return (kind == XMM);
	}

	/** Is this item on the FPU stack */
	final boolean isFPUStack() {
		return (kind == FPUSTACK);
	}

	/** Is this item a local variable */
	final boolean isLocal() {
		return (kind == LOCAL);
	}

	/** Is this item a constant */
	final boolean isConstant() {
		return (kind == CONSTANT);
	}
	
	/**
	 * Gets computional category of this item.
	 * @return int
	 */
	public int getCategory() {
		return 1;
	}
	
	/**
	 * Gets offset to ebp.
	 * @return short
	 */
	public short bpOffset() {
		return bpOffset;
	}
	
	/**
	 * Gets xmm.
	 * @return X86Register.XMM
	 */
	public X86Register.XMM getXMM() {
		return xmm;
	}
	
	public abstract void load(EmitterContext c);
	public abstract void loadGPR(EmitterContext c);
	
	public final void loadIf(EmitterContext c, int mask) {
		if ((kind & mask) > 0) {
			load(c);
		}
	}
	
	public abstract Item clone(EmitterContext c);
	public abstract void push(EmitterContext c);
	public abstract void pushFPU(EmitterContext c);
	public abstract void release(EmitterContext c);
	public abstract void spill(EmitterContext c, X86Register r);
	
	public final void spillUsed(EmitterContext c, X86Register r) {
		if (uses(r)) {
			spill(c, r);
		}
	}
	
	public abstract boolean uses(X86Register reg);
	public abstract boolean usesVolatileRegister(X86RegisterPool pool);
}
